#ifndef DOWNCLIENT_H
#define DOWNCLIENT_H

/* https://www.jianshu.com/p/f976ba6e112b 代码规范 */

#include <QMainWindow>
#include <QListWidgetItem>
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <QThread>
#include <QDebug>
#include <QProcess>
#include <QTimer>
#include <QKeyEvent>

#include "configfile.h"
#include "filedata_t.h"
#include "loginwindow.h"
#include "operate/download.h"
#include "operate/upload.h"
#include "operate/pathdelete.h"

#define LOG(fmt, ...)   this->log(fmt, ##__VA_ARGS__)
#define LOGL(level, fmt, ...)  this->log(level, fmt, ##__VA_ARGS__)

QT_BEGIN_NAMESPACE
namespace Ui {
class DownClientLoopThread;
class DownClient;
}
QT_END_NAMESPACE

class DownClientLoopThread : public QThread
{
    Q_OBJECT

public:
    DownClientLoopThread(unsigned long intervalSeconds = 1,
                         const QString &taskName = "",
                         QWidget *parent = nullptr
                          ):QThread(parent) {
        this->intervalSeconds   = intervalSeconds;
        this->taskName          = taskName;
        this->running = false;
    }
    void setIntervalSeconds(unsigned long seconds) {
        this->intervalSeconds = seconds;
    }
    unsigned long getIntervalSeconds() {
        return this->intervalSeconds;
    }
    void stop() {
        qDebug() << "DownClientLoopThread::stop";
        running = false;
    }
    void resetCounter() {
        qDebug() << "DownClientLoopThread::" << __FUNCTION__ << this->intervalSeconds;
        this->counter = this->intervalSeconds;
    }
    void run() override {
        qDebug() << QString("%1 started.").arg(this->taskName);
        resetCounter();
        this->running = true;
        while(this->running) {
            emit taskFuncRun();
            if(this->intervalSeconds != 0) {
//                QThread::sleep(this->intervalSeconds);
                resetCounter();
                while(--this->counter && this->running) {
                    QThread::sleep(1);
                }
            }
        }
        qDebug() << QString("%1 stoped.").arg(this->taskName);
    }
private:
    unsigned long intervalSeconds;
    unsigned long counter;
    QString taskName;
    bool running;
signals:
    void taskFuncRun();
};

class DownClient : public QMainWindow
{
    Q_OBJECT
    enum Status {
        NO_ERROR = 0,
        /* Custom error info */
        INIT_ERROR,
        JSON_ERROR,
    };

public:
    DownClient(QWidget *parent = nullptr);
    ~DownClient();
    Status heartbeatStart();
    Status reloadConfig();
    QWidget *getSourceCentralWidget();
    QRect getSourceWindowRect();

private:
    Ui::DownClient *ui;
    ConfigFile *settings;
    QString currentPath;                        //当前隔离器操作路径
    QString currentDownDir;                     //当前下载路径
    QString currentUpDir;                       //当前上传路径
    QTimer *heartbeatTimer;
    bool isHeartbeating;
    DownClientLoopThread *heartbeatThread;      //心跳线程
    QNetworkAccessManager *heartbeatNetManager; //网络心跳管理类
    QList<file_t> fileDataList;                 //文件隔离器当前文件列表的文件信息
    QList<file_t> downFileDataList;             //下载时用到的文件信息
    Download *downloadTask;                     //线程下载
    QProcess *downloadProcess;                  //进程下载
    Upload *uploadTask;                         //线程上传
    PathDelete *deleteTask;                     //删除操作
    QNetworkAccessManager *downloadNetManager;  //测试下载网络管理类
    QWidget *sourceCentralWidget;               //主窗口的源widget
    LoginWindow *loginWindow;                   //登录窗口
    QRect sourceWindowRect;                     //用于保存原始窗口Rect
    QTimer *pushBtnDownCursorEnterTimer;        //当鼠标移入 下载按钮 触发用到的定时器，用于鼠标悬停在下载按钮上以便打印下载路径
    QTimer *pushBtnDownCursorPressedTimer;      //当鼠标按下 下载按钮 触发用到的定时器，用于鼠标长按时触发 选择下载路径弹框


private slots:
    /* heartbeat */
    void heartbeat();
    void heartbeatTimeout();
    void heartbeatResponse(QNetworkReply* reply);
    /* download */
    void downloadFinished(int code, QString errorString);
    void downloadFinishedTest(QNetworkReply* reply);
    void downloadProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
    void downloadProcessReadData();
    /* upload */
    void uploadFinished(int code, QString errorString);
    /* delete */
    void deleteFinished(int code, QString errorString);


    void on_pushButtonUpperDir_clicked();

    void on_listWidgetDir_itemDoubleClicked(QListWidgetItem *item);

    /* download pushButton slots */
    void on_pushButtonDownload_clicked();
    void on_pushButtonDownload_pressed();
    void on_pushButtonDownload_released();
    void on_pushButtonDownload_CursorEnter();
    void on_pushButtonDownload_CursorLeave();
    /* 下载按钮 用到的两个定时器 超时 的槽函数 */
    void pushBtnDownCursorEnterTimerTimeout();
    void pushBtnDownCursorPressedTimerTimeout();

    void on_pushButtonSelectDownDir_clicked();

    void on_pushButtonUpload_clicked();

    void on_pushButtonDelete_clicked();

    void on_pushButtonAbout_clicked();

    void on_checkBoxRunScript_stateChanged(int arg1);



private: /* method */
    Status init();
    Status deinit();
    Status parseResponseDataToFileDataList(const QByteArray &jsonArray);
    Status updateUIByFileDataList();
    Status returnLoginWindow();
    Status down_done_script();
    void processRun();
    /* 用于窗口下方信息输出的两个函数 */
    int log(const char *format, ...);
    int log(QtMsgType level, const char *format, ...);

protected:
    bool eventFilter(QObject *target, QEvent *event) override;
    void keyReleaseEvent(QKeyEvent *ev) override;
};
#endif // DOWNCLIENT_H
